#include <unistd.h>
#include <iostream>

#include "bio.h"
#include "bio_web.h"
using bio::async;
using bio::bytes;
using bio::log;
using bio::TcpClient;
using bio::TcpServer;
using bio::web::CIMap;

async<void> accept_client(TcpClient client, sockaddr_in6 addr, TcpServer& server) {
    log("accepted a client!");
    std::cout << "from ip: " << bio::sockaddr_to_string(addr) << std::endl;
    bio::web::ParserContext ctx;
    co_await ctx.parse(client);

    std::cout << "request: " << ctx.method.to_string() << " " << ctx.req_path.to_string()
              << std::endl;
    for (auto& it : ctx.headers) {
        std::cout << it.first << ": " << it.second << std::endl;
    }

    co_await client.write(
        "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 11\r\n\r\nSample text");
    log("closing connection");
    client.shutdown();
    co_return;
}

async<void> test() {
    log("Testing yield");
    co_await bio::yield();
    log("resumed from yield");
    log("starting up tcp server on 1337");
    TcpServer serv{1337, [](TcpClient client, struct sockaddr_in6 addr, TcpServer& server) {
                       background(accept_client(std::move(client), addr, server));
                   }};
    bio::signal(SIGINT, [&serv]() { serv.shutdown(); bio::signal_del(SIGINT); });
    log("awaiting shutdown");
    co_await serv.wait_shutdown();
    bio::signal_del(SIGINT);
    co_return;
}

int main() {
    bio::init();

    try {
        bio::run(test());
    } catch (bio::errno_exception& e) {
        std::cout << "errno: " << e.what() << std::endl;
    } catch (...) {
        std::cout << "unknown exception" << std::endl;
    }

    log("back to main");

    bio::destroy();

    return 0;
}
